﻿
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Text;

namespace Anno.DynamicApi
{
    /// <summary>
    /// 调用本地DLL
    /// </summary>
    public class CSScriptExecutor : BaseExecutor
    {
        public CSScriptExecutor(ApiInfo apiInfo) : base(apiInfo, ExecutorType.CSScript)
        {
            //FullClassName = $"C{Guid.NewGuid().ToString("N")}E";
            // Method = $"A{Guid.NewGuid().ToString("N")}D";
        }

        /// <summary>
        /// 动态编译引擎-CS-Script 代码
        /// </summary>
        public string CSScriptCode { get; set; }

        string _FullClassName= "";
        /// <summary>
        /// 类名
        /// </summary>
        private string FullClassName
        {
            get
            {
                if (_FullClassName.IsNullOrEmpty())
                    _FullClassName = string.IsNullOrEmpty(ApiInfo?.KeyWord.Replace("/","_")) ? $"C{Guid.NewGuid().ToString("N")}E" : ApiInfo?.KeyWord.Replace("/", "_") + "_FullClassName"; 
                return _FullClassName;
            }
        }

        string _ActionMethod = "";
        /// <summary>
        /// 执行方法
        /// </summary>
        private string Method
        {
            get
            {
                if (_ActionMethod.IsNullOrEmpty())
                    _ActionMethod = string.IsNullOrEmpty(ApiInfo?.KeyWord.Replace("/", "_")) ? $"A{Guid.NewGuid().ToString("N")}E" : ApiInfo?.KeyWord.Replace("/", "_") + Guid.NewGuid().ToString("N") + "_ActionMethod"; 
                return _ActionMethod;
            }
        }
        public void RemoveActionMethod()
        {
            RuntimeCodeCompiler.RemoveFromCache(Method);
        }

        public CSScriptExecutor(System.Xml.XmlNode xmlNode, ApiInfo apiInfo) : base(xmlNode, apiInfo, ExecutorType.CSScript)
        {
            ExecType = ExecutorType.CSScript;
            Name = ExecType.ToString();

            if (xmlNode == null || apiInfo == null || xmlNode.NodeType == System.Xml.XmlNodeType.Comment)
            {
                return;
            }
            Init(xmlNode, apiInfo);
        }
		public CSScriptExecutor(Newtonsoft.Json.Linq.JToken xmlNode, ApiInfo apiInfo) : base(xmlNode, apiInfo, ExecutorType.CSScript)
        {
            ExecType = ExecutorType.CSScript;
            Name = ExecType.ToString();

            if (xmlNode == null || apiInfo == null)
            {
                return;
            }
            Init(xmlNode, apiInfo);
        }
        public override void Init(System.Xml.XmlNode ExecutorNode, ApiInfo apiInfo)
        {
            base.Init(ExecutorNode, apiInfo);
            try
            {
                if (ExecutorNode == null || apiInfo == null || ExecutorNode.NodeType == System.Xml.XmlNodeType.Comment)
                {
                    return;
                }
                Name = ExecutorNode.GetXmlNodeAttributeValue( "Name", Name);
                CSScriptCode = ExecutorNode.GetXmlNodeAttributeValue( "CSScriptCode");
                if (string.IsNullOrWhiteSpace(CSScriptCode))
                {
                    CSScriptCode = ExecutorNode.InnerText;
                }
            }
            catch { }
        }
        public override void Init(Newtonsoft.Json.Linq.JToken ExecutorNode, ApiInfo apiInfo)
        {
            base.Init(ExecutorNode, apiInfo);
            try
            {
                if (ExecutorNode == null || apiInfo == null)
                {
                    return;
                }
                Name = ExecutorNode.GetXmlNodeAttributeValue("Name", Name);
                CSScriptCode = ExecutorNode.GetXmlNodeAttributeValue("CSScriptCode");
            }
            catch { }
        }
        ///// <summary>
        ///// 返回JSON对象
        ///// </summary>
        //public override object JObject
        //{
        //    get
        //    {
        //        var bJObject = base.JObject as IDictionary<string, object>;

        //        bJObject[nameof(CSScriptCode)] = CSScriptCode;

        //        return bJObject;
        //    }
        //}
        public override IDictionary<string, object> DicAttrs
        {
            get
            {
                var bJObject = base.DicAttrs;

                bJObject[nameof(CSScriptCode)] = CSScriptCode;

                return bJObject;
            }
        }
        //---------------------------------------------------------------------------------------------------------------------------------
        protected override object Executor(object input)
        {
            try
            {
                var scriptCode = new StringBuilder();
                scriptCode.AppendLine("using System; ");
                scriptCode.AppendLine("using System.Collections.Generic;");
                scriptCode.AppendLine("");
                scriptCode.AppendLine("using Anno;");
                scriptCode.AppendLine("using Anno.DynamicApi;");
                //scriptCode.AppendLine("using Anno.DynamicApi;");
                //scriptCode.AppendLine("using Anno.DynamicApi.Common;");
                //scriptCode.AppendLine("using Anno.DynamicApi.Models;");
                scriptCode.AppendLine("");
               // scriptCode.AppendLine("using Anno.DynamicApi;");
               // scriptCode.AppendLine("using Anno.DynamicApi.Common;");

                scriptCode.AppendLine($"public class {FullClassName}");
                scriptCode.AppendLine("{");
                scriptCode.AppendLine("public IDictionary<string, string> DIC_Headers { get;set;}");
                scriptCode.AppendLine("public dynamic G_Headers { get { return DIC_Headers.ToDynamic();}}");
                scriptCode.AppendLine($"   public object {Method}(dynamic input)");
                scriptCode.AppendLine("   {");
                //scriptCode.AppendLine("         DIC_Headers = Anno.DynamicApi.PubFun.GetDicHeaders(request);");
                scriptCode.AppendLine(CSScriptCode);
                scriptCode.AppendLine("    }");
                scriptCode.AppendLine("}");

                dynamic dyinput = (input == null ? new object() : input).ToDynamic();
                //return ApiResult.Success(PubFun.CSScriptCodeInvoke(scriptCode.ToString(), FullClassName, Method, request, dyinput));
                var jsret = PubFun.CSScriptCodeInvoke(scriptCode.ToString(), FullClassName, Method, dyinput);
                return getJsonResult(jsret);
            }
            catch (Exception ex)
            {
                return ApiResult.Exception(ex);
                //throw ex;
                //var error =ex.GetExceptionMessage();
                //Console.WriteLine(error);
                //WindowsService.Log.Log.Error(error);
                //return null;
            }
        }
    }
}
